package q2d.client.controllers;

import java.util.LinkedList;
import java.util.Random;

import q2d.client.worlds.GameWorld;
import q2d.common.CollisionDetector;
import q2d.common.models.units.*;


public class FXController extends Controller {
 
	// referencja swiat a gry:
	private GameWorld gameWorld;
	private WallHit wallHit[];
	private CollisionDetector collisionDetector = new CollisionDetector();
	
	
	
	public FXController(int game_width, int game_height, GameWorld game_World){
		super(game_width, game_height);
		gameWorld = game_World;
	}
	
	@Override
	public void controll(long elapsedTime){
		if(isWorking==true){
			
			// petla obslugujaca "dymki" po strzale
			for(int i = 0; i< gameWorld.fxSmokesList.size();i++){
				
				Smoke smoke = gameWorld.fxSmokesList.get(i);
				smoke.x += gameWorld.fxSmokesList.get(i).vx;
				smoke.y += gameWorld.fxSmokesList.get(i).vy;
				smoke.distance -= Math.sqrt(smoke.vx*smoke.vx+smoke.vy*smoke.vy);
				smoke.vy *= 0.75;
				smoke.vx *= 0.75;
				
				smoke.anim.update();

				if(smoke.distance < 0.9 || (Math.abs(smoke.vx)<0.4) && Math.abs(smoke.vy)<0.4 || collisionDetector.isBulletMapCollision(gameWorld.gameMap, smoke.x, smoke.y, smoke.vx, smoke.vy) >= 0){	
					gameWorld.fxSmokesList.remove(i);
				}
			}

			for(int i = 0; i<gameWorld.fxMessageList.size(); i++){
				Message message = gameWorld.fxMessageList.get(i);
				
				message.timeElapsed += elapsedTime;
				
				if(message.timeElapsed >= message.timeToErase){
					gameWorld.fxMessageList.remove(i);
				}
				
			}
			
			
			// petla obslugujaca trafienia w sciane
			for(int i = 0; i<gameWorld.fxWallHitsList.size();i++){
				
				WallHit wallHit = gameWorld.fxWallHitsList.get(i);
				
				wallHit.TimeElapsed += elapsedTime;
				wallHit.x += wallHit.vx;
				wallHit.y += wallHit.vy;
				wallHit.vy *= 0.85;
				wallHit.vx *= 0.85;
				wallHit.distance -= Math.sqrt(wallHit.vx*wallHit.vx+wallHit.vy*wallHit.vy);
				
				
				if((Math.abs(wallHit.vx)<0.4)){
					wallHit.vy *= 0.01;
				}
				if((Math.abs(wallHit.vy)<0.4)){
					wallHit.vx *= 0.01;
				}

					
				if(wallHit.distance < 0 || wallHit.TimeElapsed >= wallHit.timeToErese){	
					gameWorld.fxWallHitsList.remove(i);
				
				}
				
			}
		}//koniec if
		else{
			return;
		}
		// petla obslugujaca trafienia w graczy
		for(int i = 0; i < gameWorld.fxPlayerHitList.size(); i++){
			PlayerHit playerHit = gameWorld.fxPlayerHitList.get(i);
			playerHit.timeElapsed += elapsedTime;
			
			if(playerHit.timeElapsed >= playerHit.timeToErase){
				gameWorld.fxPlayerHitList.remove(i);
			}
			
		}
	}//koniec controll
	
	@Override
	public void enableControll(){
		if(isWorking == false) isWorking = true;
		else return;
	}
	@Override
	public void disableControll(){
		if(isWorking == true) isWorking = false;
		else return;
	}


	/**
	 * Metoda wysyla dymki ze strzalu
	 * 
	 * @param x lufy
	 * @param y lufy
	 * @param dx predkosc x  pocisku	
	 * @param dy predkosc y  pocisku
	 */
	public void addFxSmoke(int x, int y, double dx, double dy){
		Smoke smoke = new Smoke();
		double scale = (12 / Math.sqrt(dx*dx+dy*dy));
		double angleDifference = Math.random()*(Math.PI/9)-Math.PI/18;
		smoke.x = x;
		smoke.y = y;

		/* obrot wektora
		 *             [cosA  sinA 0]
		 * [x, y, 1] x [-sinA cosA 0] = [x*cosA - y*sinA, x*sinA+y*cosA, 1]
		 *             [ 0     0   1]
		 */

		smoke.vx = scale*(dx*Math.cos(angleDifference-Math.PI/2) - dy*Math.sin(angleDifference-Math.PI/2));
		smoke.vy = scale*(dx*Math.sin(angleDifference-Math.PI/2) + dy*Math.cos(angleDifference-Math.PI/2));

		gameWorld.fxSmokesList.add(smoke);

	}// koniec addSmoke


	/**
	 * 
	 * 
	 * 
	 * @param x punkt kolizji ze sciana
	 * @param y	punkt kolizji ze sciana
	 * @param dx predkosc pocisku
	 * @param dy predksoc pocisku
 	 */
	public void addWallHitExplosion(int x, int y, double dx, double dy){
		
		final int liczaOdpryskow = 5;
		wallHit = new WallHit[liczaOdpryskow];
		
		int mnoznik=0;
		for(int i = 0; i < liczaOdpryskow; i++){
			
			wallHit[i] = new WallHit();
			wallHit[i].x = x;
			wallHit[i].y = y;			

			if(i%2 == 0) mnoznik = 1; else mnoznik = -1;
			
			
			wallHit[i].vx = dx -Math.random()*8*mnoznik;
			wallHit[i].vy = dy -Math.random()*8*mnoznik;
			
			double scale = (wallHit[i].speed / Math.sqrt(dx*dx+dy*dy)); 
			double mnoznikPredkosciX = Math.random();
			
			wallHit[i].vx = wallHit[i].vx * scale *(-1); 
			wallHit[i].vy = wallHit[i].vy * scale *(-1);
			wallHit[i].distance *= mnoznikPredkosciX;


			gameWorld.fxWallHitsList.add(wallHit[i]);
			
		}
		

	
	}// koniec addHitWallExplosion



	/**
	 * Dodaje trafienie w gracza.
	 * @param x
	 * @param y
	 * @param vx
	 * @param vy
	 */
	public void addPlayerHit(int x, int y){
		gameWorld.fxPlayerHitList.add(new PlayerHit(x, y));
	}
	
	public void addPlayerMessage(int x, int y, String messageType){
		gameWorld.fxMessageList.add(new Message(x,y,messageType));
	}

}

